主题
8节点64×V100 PCIe 集群 · 大模型训练全套落地方案
版本:V1.0 适用前提:8台裸金属,每台8×NVIDIA V100 PCIe 32GB(共64卡),无NVLink,补齐InfiniBand互联 目标:跑通 70B~130B 级模型的分布式训练(Megatron-DeepSpeed / FSDP 双方案) 文档性质:从采购上架到验收移交的端到端实施手册,可直接作为运维SOP下发
第零章 · 总体架构与执行路线
0.1 集群逻辑架构
┌─────────────────────────────────────────────────────────────┐
│ K8S + Volcano 调度层 │
├─────────────────────────────────────────────────────────────┤
│ gpu-node-0 gpu-node-1 gpu-node-2 ... gpu-node-7 │
│ 8×V100 PCIe 8×V100 PCIe 8×V100 PCIe 8×V100 PCIe │
│ 1×ConnectX 1×ConnectX 1×ConnectX 1×ConnectX │
├─────────────────────────────────────────────────────────────┤
│ IB 交换机(EDR 100G / HDR 200G,全互联胖树) │
├─────────────────────────────────────────────────────────────┤
│ 共享存储:NFS/Lustre(checkpoint + 数据集 + 容器镜像仓库) │
└─────────────────────────────────────────────────────────────┘0.2 并行策略(锁死)
| 维度 | 取值 | 说明 |
|---|---|---|
| TP(张量并行) | 1 | 纯PCIe无NVLink,节点内8卡互联带宽不足以支撑TP |
| PP(流水线并行) | 8 | 跨节点流水,通信频次低,匹配IB带宽 |
| DP(数据并行) | 8 | 64卡 ÷ (TP1 × PP8) = DP8;原稿笔误写成DP=1,特此更正 |
| 显存优化 | ZeRO-3 + CPU Offload | V100 32GB 跑 70B+ 必须开 offload_param |
| 精度 | FP16 + 激活重计算 | V100 不支持 BF16(需Ampere+),统一用 FP16 |
| 注意力 | 原生 SDPA / 自定义实现 | FlashAttention 仅支持 SM80+(A100起),V100(SM70)装不上,原稿 --use-flash-attn 必须删除 |
0.3 实施路线总览
阶段一(1-3天) 阶段二(2-4天) 阶段三(3-5天) 阶段四(2-3天) 阶段五(1天)
采购验收 → 网络与基础环境 → K8S+Volcano调度 → 训练跑通调优 → 验收移交
├ IB调通 ├ Gang调度 ├ NCCL调优 └ SOP归档
├ 驱动/CUDA ├ RDMA DevicePlugin ├ 70B冒烟
└ 存储挂载 └ 镜像准备 └ 断点续训0.4 角色分工建议
| 角色 | 职责 |
|---|---|
| 硬件/机房 | 上架、布线、IB光模块插拔、供电核算 |
| 系统运维 | OS安装、驱动、CUDA、Docker、存储挂载 |
| 网络 | IB子网规划、子网管理器、NCCL网络参数 |
| 平台 | K8S集群、Volcano、监控告警 |
| 算法/训练 | 并行配置、ds_config、启动脚本、loss验证 |
第一章 · 硬件采购与上架验收
1.1 采购清单(补采部分)
| 物料 | 规格 | 数量 | 备注 |
|---|---|---|---|
| IB网卡 | ConnectX-5 EDR 100G 单口(或 ConnectX-6 HDR 200G) | 8 | 每节点1张,PCIe x16 |
| IB交换机 | Mellanox SB7890(EDR 36口)或 QM8700(HDR 40口) | 1 | 8节点接入,留扩容口 |
| AOC/DAC线缆 | EDR 100G QSFP28,3~5米 | 8 | 同机房用DAC更省 |
| 光模块+AOC | 若跨机柜距离>5米 | 按需 | |
| 子网管理 | 交换机自带SM(QM8700内置)或独立节点跑opensm | 1 | 见1.4 |
关键确认:IB网卡必须插在与GPU同侧NUMA的PCIe x16槽位(x8会带宽腰斩),上架前先查主板槽位图。
1.2 上架检查表
- [ ] 每节点8张V100全部上电识别:
lspci | grep -i nvidia | wc -l= 8 - [ ] IB卡插入x16槽位,金手指插到底,卡扣到位
- [ ] IB线缆两端插紧,交换机端口灯绿(LinkUp)
- [ ] 供电核算:单节点8×V100(250W) + 双CPU + 风扇 ≈ 3.5kW,机柜PDU留20%余量
- [ ] 散热:V100 PCIe被动散热卡依赖机箱风道,确认前进后出、风速达标
1.3 节点命名与IP规划(示例)
| 节点 | 管理网IP | IB网IP | 主机名 |
|---|---|---|---|
| 0 | 10.0.1.10 | 192.168.100.10 | gpu-node-0 |
| 1 | 10.0.1.11 | 192.168.100.11 | gpu-node-1 |
| … | … | … | … |
| 7 | 10.0.1.17 | 192.168.100.17 | gpu-node-7 |
- IB子网单独一个网段(192.168.100.0/24),与管理网物理隔离
/etc/hosts全节点同步写入8台主机名 ↔ IB IP映射
1.4 IB子网管理器(SM)
- 用QM8700/SB7890这类管理型交换机:开启内置SM即可,无需额外配置
- 用非管理型交换机:选一台管理节点(非GPU节点)常驻跑
opensm:
bash
yum install -y opensm
systemctl enable --now opensm
# 验证
sminfo | grep -E "sm lid|state"第二章 · 硬件拓扑测绘(必做,存档)
在每台机器执行,结果存档到 拓扑测绘-节点名.txt:
bash
# GPU 互联拓扑(确认是 PCIe 不是 NVLink)
nvidia-smi topo -m
# NUMA 与 PCIe 亲和(V100 跨 NUMA 通信会慢一倍)
lscpu | grep -A3 "NUMA node(s)"
nvidia-smi -q | grep -i "PCI Bus ID"
cat /sys/class/net/ib0/device/numa_node
# IB 网卡状态
ibstat | grep -E "State|Rate|Port"
ibv_devices判定标准:
topo -m里 GPU 间显示PIX(同PCIe switch)或SYS(跨CPU)都正常,绝不能出现 NVLink 误报- IB 卡
State: Active,Rate 显示 100(EDR)或 200(HDR) - IB 卡 NUMA 尽量和所绑 GPU 同侧;若跨NUMA,记录下来,后续绑核时规避
附:GPU↔NUMA↔IB 亲和速查脚本
bash
#!/bin/bash
# 保存为 numa_affinity_check.sh,每节点执行
for gpu in /sys/class/nvidia/gpu*/device; do
echo "$(basename $(dirname $gpu)): NUMA=$(cat $gpu/numa_node)"
done
echo "IB: NUMA=$(cat /sys/class/net/ib0/device/numa_node)"第三章 · 基础环境安装(8节点统一)
3.1 操作系统与内核
- 推荐 Ubuntu 20.04/22.04 LTS 或 Rocky Linux 8/9,内核 ≥ 4.15(GDR需要)
- 关闭 NUMA balancing(防止训练进程被迁移跨NUMA):
bash
echo "kernel.numa_balancing=0" >> /etc/sysctl.conf
sysctl -p- 关闭ASLR随机化对perf的影响(可选)、开启hugepage(CPU offload受益):
bash
echo "vm.nr_hugepages=1024" >> /etc/sysctl.conf
sysctl -p3.2 NVIDIA 驱动 + CUDA
bash
# V100 用 525+ 驱动,CUDA 11.8(对老卡兼容最好)
# Ubuntu 示例:
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run
sudo sh cuda_11.8.0_520.61.05_linux.run # 只装驱动+CUDA toolkit,不装sample
nvidia-smi # 确认8卡全识别,驱动525+
nvcc --version注意:V100 计算能力 SM70,CUDA 12.x 部分新版框架已放弃优化,建议锁 CUDA 11.8 + PyTorch 1.13/2.0,兼容性最好。
3.3 MLNX_OFED(IB驱动栈)
bash
# 下载对应OS版本的 MLNX_OFED(≥5.4)
wget https://content.mellanox.com/ofed/MLNX_OFED-5.8-3.0.7.0/MLNX_OFED_LINUX-5.8-3.0.7.0-ubuntu20.04-x86_64.tgz
tar xf MLNX_OFED_LINUX-*.tgz && cd MLNX_OFED_LINUX-*
sudo ./mlnxofedinstall --with-nvmf --with-nfsrdma # 视需要加组件
sudo /etc/init.d/openibd restart
# 验证
ofed_info -s | head -1
ibstat | grep -E "State|Rate"3.4 GPUDirect RDMA(GDR)内核模块
bash
# CUDA 11.4+ 推荐 nvidia-peermem(随驱动自带)
modprobe nvidia-peermem
lsmod | grep peermem
# 老内核/老驱动用 nv_peer_mem(需从GDRCopy源码编译)
# git clone https://github.com/Mellanox/nv_peer_memory.git && cd nv_peer_memory
# ./build_module.sh && insmod nv_peer_mem.ko3.5 Docker + NVIDIA Container Toolkit
bash
# Docker
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
# NVIDIA Container Toolkit
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list \
> /etc/apt/sources.list.d/nvidia-docker.list
apt-get update && apt-get install -y nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker
# 验证
docker run --rm --gpus all nvcr.io/nvidia/cuda:11.8.0-base-ubuntu20.04 nvidia-smi3.6 共享存储挂载
所有节点挂载同一套共享存储,用于 checkpoint / 数据集 / 代码:
bash
# NFS 示例(生产建议 Lustre/GPFS,小规模 NFS 够用)
mkdir -p /shared/{ckpt,dataset,code}
mount -t nfs <nfs-server>:/export/ckpt /shared/ckpt
mount -t nfs <nfs-server>:/export/dataset /shared/dataset
mount -t nfs <nfs-server>:/export/code /shared/code
# 写进 /etc/fstab 持久化
# <nfs-server>:/export/ckpt /shared/ckpt nfs defaults,_netdev 0 0IO压测(确保读带宽 ≥ 2GB/s,否则 dataloader 成瓶颈):
bash
fio --name=readtest --directory=/shared/dataset --rw=read --bs=1M \
--size=10G --numjobs=8 --runtime=60 --time_based --group_reporting第四章 · IB 网络调通与 NCCL 环境锁死
4.1 IB 连通性测试
bash
# 节点A(server):
ib_write_bw -d mlx5_0 &
# 节点B(client):
ib_write_bw -d mlx5_0 192.168.100.10
# 预期:EDR ~97 Gb/s,HDR ~195 Gb/s8节点两两全测一遍(或至少测任意两两组合各一次),结果存档。
4.2 NCCL 全局环境变量(写进 /etc/profile.d/nccl.sh)
针对纯PCIe + IB场景的固定安全值:
bash
# ============ 通信后端 ============
export NCCL_IB_DISABLE=0
export NCCL_SOCKET_IFNAME=ib0
export NCCL_IB_HCA=mlx5_0
# GID_INDEX=3 仅用于 RoCE(以太网跑RDMA);纯IB默认不用设
# export NCCL_IB_GID_INDEX=3 # 纯IB场景注释掉;若误用RoCE再打开
# ============ 纯 PCIe 无 NVLink:强制关 P2P,防 CUDA 上下文死锁 ============
export NCCL_P2P_DISABLE=1
export NCCL_P2P_LEVEL=PIX
# ============ 跨节点 Tree 算法更稳 ============
export NCCL_ALGO=Tree
export NCCL_PROTO=Simple
# ============ PCIe 场景 buffer 调小,IB 场景 channel 调大 ============
export NCCL_BUFFSIZE=16777216
export NCCL_MIN_NCHANNELS=16
export NCCL_MAX_NCHANNELS=32
# ============ GDR:V100 支持 GPUDirect RDMA ============
export NCCL_NET_GDR_LEVEL=2 # SYS 级即可,不要强设 3/5 防回退
# ============ 超时与异步错误处理(防 hang) ============
export NCCL_SOCKET_TIMEOUT=6000
export NCCL_ASYNC_ERROR_HANDLING=1
# ============ 调试开关(调通后改 WARN) ============
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=INIT,NET修正说明:原稿
NCCL_IB_GID_INDEX=3是 RoCE(RDMA over Converged Ethernet)专用,纯IB场景无需设置,保留会导致部分NCCL版本报GID解析失败。纯IB建议注释掉。
4.3 单机/双机 NCCL 冒烟测试
先不碰 K8S,裸机验证:
bash
# 容器内或裸机装 nccl-tests
git clone https://github.com/NVIDIA/nccl-tests.git
cd nccl-tests && make -j MPI=0
# 单机 8 卡 PCIe 带宽基线(纯 PCIe 预期 ~10-14 GB/s)
./build/all_reduce_perf -b 64M -e 2G -f 2 -g 8
# 跨两节点共16卡(IB EDR 预期 busbw > 8 GB/s)
# 用 mpirun 起:
mpirun -np 16 -H node0:8,node1:8 \
-x NCCL_IB_DISABLE=0 -x NCCL_SOCKET_IFNAME=ib0 \
-x NCCL_DEBUG=INFO \
./build/all_reduce_perf -b 64M -e 2G -f 2通过标准:
- 日志出现
NET/IB且GDRDMA字样,不是NET/Socket - 单机 all-reduce busbw > 10 GB/s
- 双机 16 卡 busbw > 8 GB/s(IB 100G 理论 ~11GB/s)
第五章 · K8S + Volcano 调度层(防死锁)
5.1 集群组件清单
| 组件 | 版本要求 | 用途 |
|---|---|---|
| K8S | ≥ 1.26 | 容器编排 |
| NVIDIA Device Plugin | 最新 | 上报 nvidia.com/gpu |
| Volcano | ≥ 1.8 | Gang Scheduling(防半启动死锁) |
| RDMA Shared Device Plugin | 最新 | 上报 rdma/rdma_shared_device_a(IB给容器用) |
| Metrics Server / Prometheus | 可选 | 监控 |
5.2 安装 Volcano
bash
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace5.3 安装 RDMA Shared Device Plugin
bash
# 用 k8s-rdma-shared-dev-plugin
kubectl apply -f https://raw.githubusercontent.com/Mellanox/k8s-rdma-shared-dev-plugin/master/images/k8s-rdma-shared-dev-plugin-config-map.yaml
kubectl apply -f https://raw.githubusercontent.com/Mellanox/k8s-rdma-shared-dev-plugin/master/images/k8s-rdma-shared-dev-plugin-ds.yaml
# 验证节点上多了 rdma 资源
kubectl describe node gpu-node-0 | grep -A3 "rdma"5.4 节点打标
bash
for i in $(seq 0 7); do
kubectl label node gpu-node-$i gpu-type=v100-pcie
kubectl label node gpu-node-$i ib-net=ib0
done5.5 NCCL ConfigMap(把第四章变量注入容器)
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nccl-defaults
data:
NCCL_IB_DISABLE: "0"
NCCL_SOCKET_IFNAME: "ib0"
NCCL_IB_HCA: "mlx5_0"
NCCL_P2P_DISABLE: "1"
NCCL_P2P_LEVEL: "PIX"
NCCL_ALGO: "Tree"
NCCL_PROTO: "Simple"
NCCL_BUFFSIZE: "16777216"
NCCL_MIN_NCHANNELS: "16"
NCCL_MAX_NCHANNELS: "32"
NCCL_NET_GDR_LEVEL: "2"
NCCL_SOCKET_TIMEOUT: "6000"
NCCL_ASYNC_ERROR_HANDLING: "1"
NCCL_DEBUG: "INFO"
NCCL_DEBUG_SUBSYS: "INIT,NET"5.6 Volcano Queue
yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: training
spec:
weight: 1
capability:
cpu: "512"
memory: "2048Gi"
nvidia.com/gpu: 645.7 Volcano Job 完整版(8机64卡 Gang)
yaml
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: v100-train-gang
spec:
schedulerName: volcano
minAvailable: 8 # 8机必须同时起,否则全 Pending
queue: training
plugins:
env: []
svc: []
maxRetry: 3
tasks:
- name: trainer
replicas: 8
template:
metadata:
labels:
app: megatron-train
spec:
hostNetwork: true # IB直通用hostNetwork最简单
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: megads
image: your-registry/megatron-deepspeed:v100-cuda118
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: nccl-defaults
env:
- name: WORLD_SIZE
value: "64"
- name: TP_SIZE
value: "1"
- name: PP_SIZE
value: "8"
- name: DP_SIZE
value: "8"
- name: MASTER_ADDR
value: "v100-train-gang-trainer-0"
- name: MASTER_PORT
value: "29500"
- name: RANK
valueFrom:
fieldRef:
fieldPath: metadata.labels['batch.volcano.sh/job-task-index']
ports:
- containerPort: 29500
resources:
limits:
nvidia.com/gpu: 8
rdma/rdma_shared_device_a: 1
requests:
nvidia.com/gpu: 8
volumeMounts:
- name: dshm
mountPath: /dev/shm
- name: ckpt
mountPath: /shared/ckpt
- name: dataset
mountPath: /shared/dataset
- name: code
mountPath: /shared/code
securityContext:
capabilities:
add: ["IPC_LOCK"] # GDR需要
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 64Gi
- name: ckpt
persistentVolumeClaim:
claimName: pvc-ckpt
- name: dataset
persistentVolumeClaim:
claimName: pvc-dataset
- name: code
persistentVolumeClaim:
claimName: pvc-code关键:
minAvailable: 8+schedulerName: volcano缺一个就会半启动死锁。hostNetwork: true让容器直接用宿主机IB协议栈,省去Macvlan/SR-IOV的复杂配置,性能无损。
5.8 PVC 模板(NFS示例)
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-ckpt
spec:
capacity:
storage: 10Ti
accessModes: ["ReadWriteMany"]
nfs:
server: <nfs-server>
path: /export/ckpt
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-ckpt
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 10Ti第六章 · 训练框架启动(双方案)
方案A:Megatron-DeepSpeed(TP1 + PP8 + ZeRO3)
6.1 ds_config.json(ZeRO-3 + V100 专用)
json
{
"fp16": {
"enabled": true,
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": { "device": "cpu", "pin_memory": true },
"offload_param": { "device": "cpu", "pin_memory": true },
"overlap_comm": true,
"contiguous_gradients": true,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_gather_fp16_weights_on_model_save": true
},
"activation_checkpointing": true,
"gradient_clipping": 1.0,
"train_micro_batch_size_per_gpu": 1,
"gradient_accumulation_steps": 2,
"train_batch_size": 128,
"steps_per_print": 10,
"wall_clock_breakdown": false
}6.2 Megatron 启动脚本
bash
#!/bin/bash
# launch_megatron.sh
set -x
deepspeed --num_nodes 8 --num_gpus 8 \
--master_addr ${MASTER_ADDR} --master_port ${MASTER_PORT} \
pretrain_gpt.py \
--num-layers 80 \
--hidden-size 8192 \
--num-attention-heads 64 \
--seq-length 2048 \
--max-position-embeddings 2048 \
--micro-batch-size 1 \
--global-batch-size 128 \
--tensor-model-parallel-size 1 \
--pipeline-model-parallel-size 8 \
--fp16 \
--recompute-activations \
--recompute-granularity selective \
--deepspeed \
--deepspeed_config ds_config.json \
--distributed-backend nccl \
--data-path /shared/dataset/gpt2/my-gpt2_text_document \
--vocab-file /shared/dataset/gpt2/gpt2-vocab.json \
--merge-file /shared/dataset/gpt2/gpt2-merges.txt \
--save /shared/ckpt/megatron-70b \
--save-interval 500 \
--log-interval 10 \
--train-iters 1000已删除
--use-flash-attn:V100(SM70)不支持 FlashAttention(需 SM80+)。Megatron 会自动回退到原生注意力实现。若想加速,可装xformers(部分算子支持SM70)或用torch.nn.functional.scaled_dot_product_attention(PyTorch 2.0+ 内置,CPU/GPU通用)。
6.3 显存保护策略
V100 32G 跑 70B+ 必须开 offload_param,若仍 OOM:
--micro-batch-size保持 1(已经最小)--seq-length降到 1024recompute-granularity从selective改为full- 检查
ds_config.json里offload_param.device确实是cpu
方案B:FSDP(PyTorch 原生,不依赖 Megatron)
适合不用Megatron生态、想快速验证或训非GPT架构的场景。
6.4 FSDP 启动脚本
python
# fsdp_train.py 关键配置
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
from torch.distributed.fsdp.fully_sharded_data_parallel import (
CPUOffload, ShardingStrategy
)
from torch.distributed.fsdp.wrap import transformer_auto_wrap_policy
model = FSDP(
model,
sharding_strategy=ShardingStrategy.FULL_SHARD, # 等价 ZeRO-3
cpu_offload=CPUOffload(offload_params=True), # 70B+ 必须开
auto_wrap_policy=functools.partial(
transformer_auto_wrap_policy,
transformer_layer_cls={TransformerBlock},
),
mixed_precision=MixedPrecision(
param_dtype=torch.float16,
reduce_dtype=torch.float16,
buffer_dtype=torch.float16,
),
device_id=torch.cuda.current_device(),
)6.5 FSDP torchrun 启动命令
bash
torchrun \
--nnodes=8 \
--nproc_per_node=8 \
--rdzv_id=v100-fsdp \
--rdzv_backend=c10d \
--rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} \
fsdp_train.py \
--model_size 70b \
--seq_len 2048 \
--batch_size 1 \
--grad_accum 2 \
--ckpt_dir /shared/ckpt/fsdp-70b6.6 两方案选型建议
| 场景 | 推荐 |
|---|---|
| 训标准GPT/LLaMA架构,追求极致吞吐 | Megatron-DeepSpeed |
| 自定义模型架构,不想改Megatron源码 | FSDP |
| 团队熟悉PyTorch生态,快速验证 | FSDP |
| 需要精细PP调度(1F1B、Interleaved) | Megatron-DeepSpeed |
第七章 · 断点续训与容错
7.1 Checkpoint 策略
save-interval建议 500 iter 一次(70B 模型单次 ckpt ~280GB,FP16 权重)- 共享存储预留 ≥ 3 倍模型大小的空间(保留最近3份)
- 开启
stage3_gather_fp16_weights_on_model_save(ds_config已含),保证 save 时权重完整聚合,避免 ZeRO-3 分片 ckpt 恢复失败
7.2 断点恢复
bash
# Megatron 自动找 latest_checkpointed_iteration.txt
--load /shared/ckpt/megatron-70b \
--no-load-optim \ # 只想恢复权重不恢复optimizer state时加
--no-load-rng7.3 节点故障演练
- 训练中途
kubectl delete pod杀掉一个 trainer - 观察 Volcano 是否按
maxRetry: 3整体重启 Job(Gang语义:一个挂,全组重调度) - 重启后
--load自动从最近 ckpt 恢复,loss 曲线应连续
第八章 · 监控与性能分析
8.1 基础监控
| 指标 | 工具 | 告警阈值 |
|---|---|---|
| GPU利用率 | nvidia-smi / DCGM Exporter | < 50% 持续5min(可能hang) |
| GPU显存 | DCGM | > 30GB(接近OOM) |
| IB带宽 | perfquery / ib counters | < 50 Gb/s(链路降级) |
| PCIe带宽 | nvidia-smi dmon | 持续 < 8 GB/s(拓扑问题) |
| CPU内存 | node_exporter | > 90%(offload溢出风险) |
8.2 训练侧关键日志
bash
# 关注这三个字段判断健康度:
# iteration 时间(每iter秒数,稳定才算调通)
# lm loss(应持续下降,前100 iter 下降明显)
# grad norm(应 < 10,持续 > 100 说明发散)
tail -f /shared/ckpt/megatron-70b/train.log | grep -E "iteration|lm loss|grad norm"8.3 性能基准(V100 参考值)
| 模型 | 并行配置 | 预期吞吐 |
|---|---|---|
| 70B | TP1/PP8/DP8, ZeRO3+offload | ~30-50 TFLOPs/卡 |
| 130B | TP1/PP8/DP8, ZeRO3+offload, seq1024 | ~25-40 TFLOPs/卡 |
若实测 < 60% 预期值,优先查:① NCCL 是否走了 Socket 而非 IB;② dataloader IO 瓶颈;③ CPU offload 换页抖动。
第九章 · 常见故障速查表
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
| NCCL 初始化 hang 住 | IB 不通 / SM 没跑 / GID 错误 | ibstat、sminfo、NCCL_DEBUG=INFO | 确认 IB State=Active;纯IB注释掉 GID_INDEX |
日志显示 NET/Socket 而非 NET/IB | NCCL 没找到 IB 设备 | ls /sys/class/infiniband/、NCCL_IB_HCA | 确认 NCCL_IB_DISABLE=0,容器内装了 libibverbs |
| 单机 8 卡 all-reduce 只有 2-3 GB/s | 误开 NVLink P2P / PCIe 降速 | nvidia-smi topo -m、nvidia-smi -q -d PERFORMANCE | NCCL_P2P_DISABLE=1;查 PCIe 协商速率是否 x16 |
| 双机 busbw < 4 GB/s | 走了 TCP / IB 线缆半速 | ib_write_bw 裸测 | 换线缆/光模块;确认 ibstat Rate=100/200 |
| 训练 OOM(CUDA out of memory) | offload 没生效 / mbs 太大 | nvidia-smi、ds_config | 确认 offload_param=cpu;mbs=1;seq降1024 |
| ZeRO-3 save ckpt 后恢复失败 | 权重没聚合就 save | ckpt 目录大小是否完整 | 开 stage3_gather_fp16_weights_on_model_save |
| Volcano Job 一半 Pod Pending | 缺 Gang 调度 / 资源不够 | kubectl describe vcjob | 确认 minAvailable=replicas;查节点 GPU/RDMA 资源 |
容器内 ibstat 没设备 | 没挂 RDMA 资源 | kubectl describe pod | 加 rdma/rdma_shared_device_a: 1 + hostNetwork: true |
| 训练 loss 突然 NaN | FP16 溢出 / 学习率过大 | grad norm 日志 | loss_scale 调小;warmup 加长;grad clipping 1.0 |
| CPU 内存爆掉(offload溢出) | offload_param+offload_opt 同时开,内存不够 | free -h、`dmesg | grep OOM` |
| dataloader 慢,GPU 等数据 | NFS IO 瓶颈 / num_workers 太少 | iostat -x 1、fio | 换 Lustre/本地SSD缓存;num_workers=8+ |
--use-flash-attn 报错 | V100 不支持 FlashAttention | pip show flash-attn | 删除该参数;用原生SDPA或xformers |
第十章 · 验收标准(上线前 Gate)
| # | 验收项 | 通过标准 |
|---|---|---|
| 1 | NCCL 网络 | nccl-tests 双机 16 卡 busbw ≥ 8 GB/s |
| 2 | Gang 调度 | Volcano Job 64 Pod 同时 Running,无 Pending |
| 3 | NCCL 路径 | 训练日志出现 NCCL INFO Trees + GDRDMA |
| 4 | 70B 跑通 | TP1/PP8/DP8 + ZeRO3 跑完 50 iter 不 OOM,loss 持续下降 |
| 5 | 故障恢复 | 拔 1 节点,Volcano 按策略重试或完整释放,无半吊子 |
| 6 | 断点续训 | kill 后重启,自动从 ckpt 恢复,loss 曲线连续 |
| 7 | 监控就绪 | GPU/IB/存储 监控面板有数据,告警规则生效 |
| 8 | 文档移交 | 拓扑测绘、NCCL变量、启动脚本、SOP 全部归档 |
附录A · 端到端实施 Checklist
【阶段一 · 采购上架】
□ IB网卡/交换机/线缆到货验收
□ IB卡插入GPU同侧NUMA的x16槽位
□ 8节点上电,lspci 识别8×V100 + 1×IB
□ IB交换机SM开启,ibstat State=Active
【阶段二 · 基础环境】
□ OS/CUDA 11.8/驱动525+ 安装
□ MLNX_OFED 安装,ib_write_bw 双机测通
□ nvidia-peermem 加载,lsmod 确认
□ Docker + nvidia-container-toolkit 装完
□ 共享存储挂载,fio 读带宽 ≥ 2GB/s
【阶段三 · 网络调优】
□ NCCL 环境变量写进 /etc/profile.d/nccl.sh
□ 单机 8 卡 all-reduce > 10 GB/s
□ 双机 16 卡 all-reduce > 8 GB/s,走 NET/IB + GDRDMA
【阶段四 · 调度平台】
□ K8S ≥1.26 就绪
□ Volcano、NVIDIA Device Plugin、RDMA Plugin 装完
□ 节点打标 gpu-type=v100-pcie
□ NCCL ConfigMap、Queue、PVC 就绪
□ Volcano Job 64 Pod 同时 Running
【阶段五 · 训练跑通】
□ Megatron-DeepSpeed 70B 跑 50 iter 不 OOM
□ loss 下降,grad norm 正常
□ 断点续训验证通过
□ FSDP 备选方案验证(可选)
【阶段六 · 验收移交】
□ 10项验收标准全过
□ 监控告警就绪
□ SOP/脚本/拓扑图归档移交运维附录B · 参考资源
- NCCL 官方文档:https://docs.nvidia.com/deeplearning/nccl/
- Megatron-DeepSpeed:https://github.com/microsoft/Megatron-DeepSpeed
- DeepSpeed ZeRO-3 配置:https://www.deepspeed.ai/docs/config-json/
- PyTorch FSDP:https://pytorch.org/docs/stable/fsdp.html
- Volcano:https://volcano.sh/
- k8s-rdma-shared-dev-plugin:https://github.com/Mellanox/k8s-rdma-shared-dev-plugin
修订记录
| 版本 | 日期 | 变更 |
|---|---|---|
| V1.0 | 2026-07-31 | 初版全套落地方案,含采购到验收全流程 |
相对原稿的关键修正:
- 并行策略 DP=1 → DP=8(64卡 ÷ TP1×PP8)
- 删除
--use-flash-attn(V100 SM70 不支持 FlashAttention)NCCL_IB_GID_INDEX=3标注为 RoCE 专用,纯IB建议注释- 补全 Volcano 完整 YAML(ConfigMap/Queue/PVC/hostNetwork)
- 补全 FSDP 备选启动方案
- 补全故障速查表(原稿为空)